/**
 * http://surenpi.com
 */
package autotest.web.framework.plugin;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.wizards.NewTypeWizardPage.ImportsManager;

/**
 * @author suren
 * @date Jul 23, 2016 11:30:03 AM
 */
public class CodeGenerator
{
	public static final String		PRIVATE	= "private";
	public static final String		PUBLIC	= "public";

	private final IType				type;
	private final ImportsManager	importsMgr;

	/**
	 * addAnnotation这个方法还需要用户手动添加包
	 * 
	 * @param type
	 *            要操作的类
	 * @param importsMgr
	 *            用于添加包引用
	 */
	public CodeGenerator(IType type, ImportsManager importsMgr)
	{
		this.type = type;
		this.importsMgr = importsMgr;

		if (this.type == null || this.importsMgr == null)
		{
			throw new NullPointerException("type和importsMgr参数不能为空");
		}
	}

	/**
	 * 添加注解。建议再一个元素上调用一次，不然可能会有问题。
	 * 
	 * @param member
	 *            要添加注解的类成员
	 * @param buf
	 *            注解内容
	 * @throws JavaModelException
	 */
	public void addAnnotation(IMember member, StringBuffer buf)
			throws JavaModelException
	{
		ISourceRange range = member.getSourceRange();
		ISourceRange docRange = member.getJavadocRange();
		IBuffer typeBuf = type.getCompilationUnit().getBuffer();
		int typeOffset = range.getOffset();
		int typeLength = range.getLength();

		if (docRange != null)
		{
			int docRangeLength = 0;
			docRangeLength = docRange.getLength();
			typeOffset += docRangeLength;
			typeLength -= docRangeLength;
		}
		buf.append(typeBuf.getText(typeOffset, typeLength));

		typeBuf.replace(typeOffset, typeLength, buf.toString());
		// TODO 有时间了，把这个方法也实现为不需要用户手动调用ImportsManager来做包导入
	}

	/**
	 * 添加属性
	 * 
	 * @param access
	 * @param fieldType
	 * @param name
	 * @return
	 * @throws JavaModelException
	 */
	public IField addField(String access, String fieldType, String name)
			throws JavaModelException
	{
		String shortFieldType = BeanUtil.getShortClass(fieldType);

		StringBuffer buf = new StringBuffer();
		buf.append(access);
		buf.append(" ");
		buf.append(shortFieldType);
		buf.append(" ");
		buf.append(name);
		buf.append(";");

		if (!shortFieldType.equals(fieldType))
		{
			importsMgr.addImport(fieldType);
		}

		return type.createField(buf.toString(), null, false, null);
	}

	/**
	 * 添加private的属性
	 * 
	 * @param fieldType
	 * @param name
	 * @return
	 * @throws JavaModelException
	 */
	public IField addField(String fieldType, String name)
			throws JavaModelException
	{
		return addField(PRIVATE, fieldType, name);
	}

	/**
	 * 给属性添加getter方法
	 * 
	 * @param attrType
	 * @param name
	 * @return
	 * @throws CoreException
	 */
	public IMethod addGetter(String attrType, String name) throws CoreException
	{
		String shortAttrType = BeanUtil.getShortClass(attrType);

		String content = CodeGeneration.getGetterMethodBodyContent(
				type.getCompilationUnit(), type.getTypeQualifiedName('.'), "",
				name, "\n");

		StringBuffer buf = new StringBuffer();
		buf.append(PUBLIC).append(" ");
		buf.append(shortAttrType);
		buf.append(" get").append(name.substring(0, 1).toUpperCase())
				.append(name.substring(1));
		buf.append("(){\n");
		buf.append(content);
		buf.append("\n}");

		if (!shortAttrType.equals(attrType))
		{
			importsMgr.addImport(attrType);
		}

		IMethod method = type.createMethod(buf.toString(), null, false, null);

		return method;
	}

	/**
	 * 给属性添加setter方法
	 * 
	 * @param attrType
	 * @param name
	 * @return
	 * @throws CoreException
	 */
	public IMethod addSetter(String attrType, String name) throws CoreException
	{
		String shortAttrType = BeanUtil.getShortClass(attrType);

		String content = CodeGeneration.getSetterMethodBodyContent(
				type.getCompilationUnit(), type.getTypeQualifiedName('.'), "",
				"this." + name, name, "\n");

		StringBuffer buf = new StringBuffer();
		buf.append(PUBLIC).append(" void set");
		buf.append(name.substring(0, 1).toUpperCase())
				.append(name.substring(1));
		buf.append("(").append(shortAttrType).append(" ").append(name)
				.append("){\n");
		buf.append(content);
		buf.append("\n}");

		if (!shortAttrType.equals(attrType))
		{
			importsMgr.addImport(attrType);
		}

		return type.createMethod(buf.toString(), null, false, null);
	}
}
